﻿using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Validation.BusinessRules;

namespace Sinacor.Servico.Bovespa.Corretagem.BusinessLogic
{
    /// <summary>
    /// Business Logic DescontoDiferenciado
    /// </summary>
    public class DescontoDiferenciado : BaseBusinessLogic
    {
        #region Constantes de Erro

        private const int ERRO_DESCONTODIFERENCIADO_PERCENTUALDIFERENTEDEZERO = 000000;
        private const int ERRO_DESCONTODIFERENCIADO_PERCENTUALNEGATIVOMINIMO = 000001;
        private const int ERRO_DESCONTODIFERENCIADO_PERCENTUALOBRIGATORIO = 000002;
        private const int ERRO_OBJETO_NULO = 109517; 

        #endregion

        #region Atributos

        ResourceAccess.DescontoDiferenciado _raDescontoDiferenciado = null;

        #endregion

        #region Construtor

        public DescontoDiferenciado()
            : base()
        {
            this._raDescontoDiferenciado = new ResourceAccess.DescontoDiferenciado();
        }

        #endregion

        #region ConsultarDescontoDiferenciado

        /// <summary>
        /// MÃ©todo ConsultarDescontoDiferenciado
        /// </summary>
        public List<BusinessEntity.DescontoDiferenciado> ConsultarDescontoDiferenciado(BusinessEntity.Parameter.ConsultarDescontoDiferenciado consultardescontodiferenciado)
        {
            return this._raDescontoDiferenciado.ConsultarDescontoDiferenciado(consultardescontodiferenciado);
        }

        #endregion

        #region ConsultarTipoDescontoDiferenciado

        /// <summary>
        /// MÃ©todo ConsultarTipoDescontoDiferenciado
        /// </summary>
        public List<BusinessEntity.TipoDescontoDiferenciado> ConsultarTipoDescontoDiferenciado()
        {
            return this._raDescontoDiferenciado.ConsultarTipoDescontoDiferenciado();
        }

        #endregion

        #region ExcluirDescontoDiferenciado

        /// <summary>
        /// MÃ©todo ExcluirDescontoDiferenciado
        /// </summary>
        public void ExcluirDescontoDiferenciado(BusinessEntity.Parameter.ExcluirDescontoDiferenciado excluirdescontodiferenciado)
        {
            this._raDescontoDiferenciado.ExcluirDescontoDiferenciado(excluirdescontodiferenciado);
        }

        #endregion

        #region SalvarDescontoDiferenciado

        /// <summary>
        /// MÃ©todo SalvarDescontoDiferenciado
        /// </summary>
        public void SalvarDescontoDiferenciado(List<BusinessEntity.DescontoDiferenciado> descontodiferenciado)
        {
            //Validar dados antes da InserÃ§Ã£o ou AtualizaÃ§Ã£o
            ValidarDescontoDiferenciado(descontodiferenciado);

            //Excluir dados antigos depois da validaÃ§Ã£o.
            foreach(BusinessEntity.DescontoDiferenciado item in descontodiferenciado) {
                
                BusinessEntity.Parameter.ExcluirDescontoDiferenciado parameter = new Sinacor.Servico.Bovespa.Corretagem.BusinessEntity.Parameter.ExcluirDescontoDiferenciado();
                parameter.CodigoTabelaPadrao = (item.CodigoTabela.HasValue ? item.CodigoTabela.Value : 0);

                ExcluirDescontoDiferenciado(parameter);
            }

            //Efetuar a InserÃ§Ã£o ou AtualizaÃ§Ã£o
            this._raDescontoDiferenciado.SalvarDescontoDiferenciado(descontodiferenciado);
        }

        #endregion

        #region ValidarDescontoDiferenciado

        /// <summary>
        /// MÃ©todo ValidarDescontoDiferenciado
        /// </summary>
        public void ValidarDescontoDiferenciado(List<BusinessEntity.DescontoDiferenciado> descontodiferenciado)
        {
            foreach (BusinessEntity.DescontoDiferenciado item in descontodiferenciado)
            {
                ValidarDescontoDiferenciado(item);                
            }
        }

        #endregion

        #region ValidarDescontoDiferenciado

        public void ValidarDescontoDiferenciado(BusinessEntity.DescontoDiferenciado descontodiferenciado)
        {
            if (descontodiferenciado.TipoDesconto.Obrigatorio.HasValue && descontodiferenciado.TipoDesconto.Obrigatorio.Value)
            {
                if (descontodiferenciado.Percentual == null)
                {
                    throw new BusinessException(ERRO_DESCONTODIFERENCIADO_PERCENTUALOBRIGATORIO);
                }

                if (descontodiferenciado.Percentual.Equals(0))
                {
                    throw new BusinessException(ERRO_DESCONTODIFERENCIADO_PERCENTUALDIFERENTEDEZERO);
                }

                if (descontodiferenciado.Percentual <= -100)
                {
                    throw new BusinessException(ERRO_DESCONTODIFERENCIADO_PERCENTUALNEGATIVOMINIMO);
                }

            }
        }

        #region ConsultarDescontosDiferenciados

        /// <summary>
        /// Consulta descontos diferenciados de uma tabela de corretagem conforme filtro
        /// </summary>
        /// <param name="parameter">ParÃ¢metro para consultar descontos diferenciados de uma tabela de corretagem conforme filtro</param>
        /// <returns>Lista de DescontoDiferenciado</returns>
        public List<BusinessEntity.DescontoDiferenciado> ConsultarDescontosDiferenciados(BusinessEntity.Parameter.FiltroDescontoDiferenciado parameter)
        {
            List<BusinessEntity.DescontoDiferenciado> listEntities = null;

            if (parameter != null)
            {
                listEntities = this._raDescontoDiferenciado.ConsultarDescontosDiferenciados(parameter);    
            }
            else
            {
                throw new BusinessException(ERRO_OBJETO_NULO);
            }

            return listEntities;
        }

        #endregion

        #region DuplicarDescontosDiferenciados

        /// <summary>
        /// Duplica descontos diferenciados baseados em uma tabela de corretagem (tabelaOrigem).
        /// </summary>
        /// <Obs>
        /// O parametro tabelaDestino deve ser passado por referencia
        /// </Obs>
        /// <param name="tabelaOrigem">Tabela Origem</param>
        /// <param name="tabelaDestino">Tabela Destino</param>
        public void DuplicarDescontosDiferenciados(BusinessEntity.Parameter.FiltroTabelaCorretagemChave tabelaOrigem, ref BusinessEntity.TabelaCorretagem tabelaDestino)
        {
            List<BusinessEntity.DescontoDiferenciado> listaDescontosDiferenciados = null;
            
            if (tabelaOrigem != null && tabelaDestino != null)
            {
                this._raDescontoDiferenciado.DuplicarDescontosDiferenciados(tabelaOrigem, new BusinessEntity.Parameter.FiltroTabelaCorretagemChave
                {
                    Codigo = (tabelaDestino.Codigo.HasValue ? tabelaDestino.Codigo.Value : 0)
                });

                listaDescontosDiferenciados = this._raDescontoDiferenciado.ConsultarDescontosDiferenciados(new BusinessEntity.Parameter.FiltroDescontoDiferenciado
                {
                    CodigoTabela = (tabelaDestino.Codigo.HasValue ? tabelaDestino.Codigo.Value : 0)
                });

                tabelaDestino.Descontos = listaDescontosDiferenciados;
            }
            else
            {
                throw new BusinessException(ERRO_OBJETO_NULO);
            }
        }

        #endregion

        #region ExcluirDescontoDiferenciado

        /// <summary>
        /// Exclui um desconto diferenciado de uma tabela de corretagem
        /// </summary>
        /// <param name="parametro">ParÃ¢metro para excluir um desconto diferenciado de uma tabela de corretagem</param>
        public void ExcluirDescontoDiferenciado(BusinessEntity.Parameter.FiltroDescontoDiferenciadoChave parametro)
        {
            if (parametro != null)
            {
                this._raDescontoDiferenciado.ExcluirDescontoDiferenciado(parametro);
            }
            else
            {
                throw new BusinessException(ERRO_OBJETO_NULO);
            }
        }

        #endregion

        #region ExcluirTodosDescontosDiferenciados

        /// <summary>
        /// Exclui todos os descontos diferenciados de uma tabela de corretagem
        /// </summary>
        /// <Obs>
        /// Para excluir todos os descontos basta informar o codigo da tabela no filtro
        /// </Obs>
        /// <param name="parameter">ParÃ¢metro para excluir todos os descontos diferenciados de uma tabela de corretagem</param>
        public void ExcluirTodosDescontosDiferenciados(BusinessEntity.Parameter.FiltroDescontoDiferenciadoChave parameter)
        {
            if (parameter.CodigoTabela.HasValue)
            {
                this._raDescontoDiferenciado.ExcluirTodosDescontosDiferenciados(parameter);
            }
            else
            {
                new BusinessException(ERRO_OBJETO_NULO);
            }
        }

        #endregion

        #region IncluirDescontoDiferenciado

        /// <summary>
        /// Inclui um desconto diferenciado
        /// </summary>
        /// <param name="entity">ParÃ¢metro para incluir um desconto diferenciado</param>
        public void IncluirDescontoDiferenciado(BusinessEntity.DescontoDiferenciado entity)
        {
            if (entity != null)
            {
                BusinessRuleValidation.ValidaInclusaoDescontoDiferenciado validaInclusaoDescontoDiferenciado = new BusinessRuleValidation.ValidaInclusaoDescontoDiferenciado();
                validaInclusaoDescontoDiferenciado.EntityToValidate = entity;

                BusinessRulesValidator validador = new BusinessRulesValidator();
                validador.AddValidation("ValidaInclusaoDescontoDiferenciado", validaInclusaoDescontoDiferenciado);

                validador.Validate();

                this._raDescontoDiferenciado.IncluirDescontoDiferenciado(entity);                
            }
            else
            {
                throw new BusinessException(ERRO_OBJETO_NULO);
            }
        }

        #endregion

        #region IncluirDescontosDiferenciados

        /// <summary>
        /// Inclui uma lista de descontos diferenciados
        /// </summary>
        /// <param name="listEntities">ParÃ¢metro para  incluir uma lista de descontos diferenciados</param>
        public void IncluirDescontosDiferenciados(List<BusinessEntity.DescontoDiferenciado> listEntities)
        {
            foreach (BusinessEntity.DescontoDiferenciado item in listEntities)
            {
                this.IncluirDescontoDiferenciado(item);
            }
        } 

        #endregion

        #endregion
    }
}
